package com.byd.fastevent;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

public abstract class FastEventReciever<T> {
	private static final int MSG_START = 0;
	private static final int MSG_EVENT = 1;
	private FastEventSender<T> mSender;
	private SendThread mThread;
	private FixedList<T> mChildBuffers;
	private FixedList<T> mMainBuffers;
	private boolean mDestroy;

	public FastEventReciever() {
		this(10);
	}

	public FastEventReciever(int bufferSize) {
		mChildBuffers = new FixedList<T>(bufferSize);
		mMainBuffers = new FixedList<T>(bufferSize);
		mThread = new SendThread();
		mThread.start();
	}

	void send(T t) {
		if(!mDestroy) {
			mChildBuffers.add(t);
			mThread.send();
		}
	}

	void attach(FastEventSender<T> sender) {
		if(!mDestroy) {
			unregisterReceiver();
			mSender = sender;
		}
	}

	/** 取消接收 */
	public void unregisterReceiver() {
		if(!mDestroy) {
			if(mSender != null) {
				mSender.unRecieve(this);
			}
			mSender = null;
		}
	}

	/** 是否已注册接收 */
	public boolean isReceive() {
		return !mDestroy && mSender != null;
	}

	/** 销毁事件接收器 */
	public void destroy() {
		if(!mDestroy) {
			mDestroy = true;
			if(mSender != null) {
				mSender.unRecieve(this);
			}
			mHandler.removeCallbacksAndMessages(null);
			mHandler = null;
			mSender = null;
			mThread.release();
			mThread = null;
		}
	}

	private class SendThread extends Thread {
		Looper looper;
		Handler handler;

		public SendThread() {
			setName("SendThread");
		}

		@Override
		public void run() {
			Looper.prepare();
			looper = Looper.myLooper();
			handler = new Handler(looper) {
				@Override
				public void handleMessage(Message msg) {
					try {
						while (!mDestroy && !mChildBuffers.isEmpty()) {
							onRecieveInner(mChildBuffers.removeFirst());
						}
					}
					catch (final Exception e) {
						send();
					}
				}
			};
			onStart();
			mHandler.sendEmptyMessage(MSG_START);
			send();
			Looper.loop();
		}

		void send() {
			if(!mDestroy && handler != null) {
				try {
					handler.removeMessages(0);
					handler.sendEmptyMessage(0);
				}
				catch (final Exception e) {
					// nothing
				}
			}
		}

		void release() {
			if(handler != null) {
				handler.removeCallbacksAndMessages(null);
			}
			handler = null;
			looper.quit();
			looper = null;
		}
	}

	private void onRecieveInner(T t) {
		if(!mDestroy && onFilter(t)) {
			try {
				onRecieve(t);
			}
			catch (final Exception e) {
				onError(e);
			}
		}
	}

	/** 事件接收器已启动
	 * 
	 * @param t */
	protected void onStart() {
		// for Override
	}

	/** 事件接收器已启动
	 * 
	 * @param t */
	protected void onStartOnMainThread() {
		// for Override
	}

	/** 筛选
	 * 
	 * @param t
	 * @return true则该事件会执行{@link #onRecieve}，false则该事件被过滤掉 */
	protected boolean onFilter(T t) {
		return true;
	}

	/** 运行在子线程上 */
	public abstract void onRecieve(T t);

	public abstract void onError(Throwable e);

	/** 将事件转发至主线程 */
	public void postOnMainThread(T t) {
		if(!mDestroy) {
			mMainBuffers.add(t);
			sendToMain();
		}
	}

	private void sendToMain() {
		mHandler.removeMessages(MSG_EVENT);
		mHandler.sendEmptyMessage(MSG_EVENT);
	}

	private Handler mHandler = new Handler(Looper.getMainLooper()) {
		@Override
		public void handleMessage(Message msg) {
			if(!mDestroy) {
				try {
					switch (msg.what) {
					case MSG_START:
						onStartOnMainThread();
						break;
					case MSG_EVENT:
						while (!mDestroy && !mMainBuffers.isEmpty()) {
							onRecieveMain(mMainBuffers.removeFirst());
						}
						break;
					default:
						break;
					}
				}
				catch (final Exception e) {
					onError(e);
					if(!mDestroy && !mMainBuffers.isEmpty()) {
						sendToMain();
					}
				}
			}
		}
	};

	/** 运行在主线程上
	 * 
	 * @param t */
	protected void onRecieveMain(T t) {
		// for Override
	}
}
